#ifndef XG_STD_H
#define XG_STD_H
///////////////////////////////////////////////////////////////////
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <mutex>
#include <vector>
#include <string>
#include <memory>
#include <cctype>
#include <atomic>
#include <iostream>
#include <algorithm>
#include <functional>

using namespace std;

#include "../clib/code.h"
#include "../clib/netx.h"

#define sp		shared_ptr
#define newsp	make_shared
#define extends virtual public

enum E_PARAM_TYPE
{
	eINT = 0,
	eBOOL = 1,
	eNULL = 2,
	eDOUBLE = 3,
	eSTRING = 4,
	eBUFFER = 5
};

#ifdef XG_LINUX

#include <dlfcn.h>

int GetLastError();

#else

#define	RTLD_NOW 0

typedef BOOL (WINAPI *QueryFullProcessPathFunc)(HANDLE, DWORD, LPSTR, PDWORD);

extern QueryFullProcessPathFunc QueryFullProcessPath;

#endif

#ifndef RGBA
inline static COLORREF RGBA(COLORREF r, COLORREF g, COLORREF b, COLORREF a)
{
	return RGB(r, g, b) | ( a << 24);
}
#endif

#ifndef RGBAF
inline static COLORREF RGBAF(double r, double g, double b, double a)
{
	return RGBA((COLORREF)(r * 255), (COLORREF)(g * 255), (COLORREF)(b * 255), (COLORREF)(a * 255));
}
#endif

inline static void COLORREFToRGBAF(COLORREF color, double *r, double *g, double *b, double *a)
{	
	u_char *s = (u_char*)(&color);

	*r = s[0] / 255.0f;
	*g = s[1] / 255.0f;
	*b = s[2] / 255.0f;
	*a = s[3] / 255.0f;
}

inline static void COLORREFToRGBA(COLORREF color, u_char *r, u_char *g, u_char *b, u_char *a)
{	
	u_char *s = (u_char*)(&color);

	*r = s[0];
	*g = s[1];
	*b = s[2];
	*a = s[3];
}

string GetErrorString();
string GetErrorString(int errcode);

///////////////////////////////////////////////////////////////////

class Object
{
public:
	virtual ~Object();
	virtual string toString() const;
	virtual const char* getClassName() const;
	virtual string attrs(const string& exclude = "") const;

	template<class TYPE> static const char* GetClassName()
	{
#ifdef _MSC_VER
		return typeid(TYPE).name() + 6;
#else
		return SkipStartString(typeid(TYPE).name(), "0123456789");
#endif
	}
};

class Mutex : public Object
{
protected:
	bool locked;
	MutexHandle mtx;

public:
	Mutex()
	{
		InitMutex(mtx);
		locked = false;
	}
	~Mutex()
	{
		FreeMutex(mtx);
	}
	void lock()
	{
		LockMutex(mtx);
		locked = true;
	}
	void unlock()
	{
		locked = false;
		UnlockMutex(mtx);
	}
	bool isLocked() const
	{
		return locked;
	}
};

class SpinMutex : public Object
{
private:
	atomic_flag flag = ATOMIC_FLAG_INIT;

public:
	void lock()
	{
		while (flag.test_and_set(memory_order_acquire));
	}
	void unlock()
	{
		flag.clear(std::memory_order_release);
	}
};

class ShareMutex : public Mutex
{
protected:
	Mutex mtx;
	u_long cnt = 0;

public:
	void lock()
	{
		while (locked) usleep(100);

		mtx.lock();

		if (cnt++ == 0) Mutex::lock();

		mtx.unlock();
	}
	void unlock()
	{
		mtx.lock();

		if (--cnt == 0) Mutex::unlock();

		mtx.unlock();
	}
	void lockRead()
	{
		lock();
	}
	void unlockRead()
	{
		unlock();
	}
	void lockWrite()
	{
		Mutex::lock();
	}
	void unlockWrite()
	{
		Mutex::unlock();
	}
};

typedef lock_guard<Mutex> Locker;
typedef lock_guard<SpinMutex> SpinLocker;
typedef lock_guard<ShareMutex> ShareLocker;

class BitSequence : public Object
{
protected:
	u_char* data;

public:
	BitSequence(void* data)
	{
		this->data = (u_char*)(data);
	}
	
public:
	void set(int idx)
	{
		BIT_SET(data[idx / 8], idx % 8, 1);
	}
	void clear(int idx)
	{
		BIT_SET(data[idx / 8], idx % 8, 0);
	}
	u_char at(int idx) const
	{
		return BIT_AT(data[idx / 8], idx % 8);
	}
	template<int idx> void set()
	{
		BIT_SET(data[idx / 8], idx % 8, 1);
	}
	template<int idx> void clear()
	{
		BIT_SET(data[idx / 8], idx % 8, 0);
	}
	template<int idx> u_char at() const
	{
		return BIT_AT(data[idx / 8], idx % 8);
	}
};

class Buffer
{
	friend class SmartBuffer;

protected:
	int sz;
	int maxsz;
	u_char* buf;

public:
	void free();
	u_char* malloc(int sz);
	u_char* truncate(int sz);

public:
	int size() const
	{
		return sz;
	}
	char* str() const
	{
		return buf ? (char*)(buf) : NULL;
	}
	u_char* ptr() const
	{
		return buf ? buf : NULL;
	}
	bool isNull() const
	{
		return buf == NULL;
	}
	int capacity() const
	{
		return maxsz;
	}

public:
	~Buffer()
	{
		free();
	}
	u_char& operator [] (int index)
	{
		return buf[index];
	}
	Buffer(int sz = 0) : sz(0), maxsz(0), buf(NULL)
	{
		if (sz > 0) malloc(sz);
	}
};

class Thread : public Object
{
public:
	bool start();

public:
	virtual void run() = 0;
};

class WorkItem : public Object
{
public:
	virtual void run()
	{
	}
	virtual bool runnable()
	{
		return true;
	}
};

class SmartBuffer : public Object
{
protected:
	sp<Buffer> buffer;

public:
	SmartBuffer clone();
	u_char* malloc(int sz);
	SmartBuffer& append(const string& str);
	SmartBuffer& append(const SmartBuffer& obj);
	SmartBuffer& operator = (const string& val);

public:
	void free()
	{
		buffer = NULL; 
	}
	int size() const
	{
		return buffer ? buffer->size() : 0;
	}
	int capacity() const
	{
		return buffer ? buffer->capacity() : 0;
	}
	char* str() const
	{
		return buffer ? buffer->str() : NULL;
	}
	u_char* ptr() const
	{
		return buffer ? buffer->ptr() : NULL;
	}
	bool isNull() const
	{
		return buffer.get() == NULL || buffer->isNull();
	}
	SmartBuffer(int sz = 0)
	{
		if (sz > 0) malloc(sz);
	}
	SmartBuffer(const string& str)
	{
		*this = str;
	}
	u_char* truncate(int sz)
	{
		return buffer->truncate(sz);
	}
	u_char& operator [] (int index)
	{
		return buffer->buf[index];
	}
};

class Exception : public Object, public exception
{
protected:
	int errcode;
	string errmsg;
	map<string, string> fields;

public:
	string toString() const;
	const char* what() const noexcept;

	int getErrorCode() const
	{
		return errcode;
	}
	const char* getErrorString() const
	{
		return errmsg.c_str();
	}
	static const char* GetErrorString(int code)
	{
        switch (code)
		{
            case XG_FAIL: return "process failed";
            case XG_SYSBUSY: return "system busy";
            case XG_DATAERR: return "invalid data";
            case XG_TIMEOUT: return "resource timeout";
            case XG_PARAMERR: return "parameter error";
            case XG_AUTHFAIL: return "permission denied";
			case XG_DAYLIMIT: return "frequent operation";
            case XG_NOTFOUND: return "resource not found";
            case XG_DUPLICATE: return "resource duplicate";
			case XG_NOTCHANGED: return "resource not changed";
            default: return "system error";
        }
    }
	const map<string, string>& getFields() const
	{
		return fields;
	}
	Exception& extra(const string& name, const string& value)
	{
		fields[name] = value;
		return *this;
	}
	Exception(int code, const string& msg = "") : errcode(code), errmsg(msg.empty() ? GetErrorString(code) : msg)
	{
	}
};

namespace stdx
{
	static string& tolower(string& str)
	{
		std::transform(str.begin(), str.end(), str.begin(), ::tolower);
		return str;
	}
	static string& toupper(string& str)
	{
		std::transform(str.begin(), str.end(), str.begin(), ::toupper);
		return str;
	}
	static string tolower(const string& str)
	{
		string res = str;
		return std::move(tolower(res));
	}
	static string toupper(const string& str)
	{
		string res = str;
		return std::move(toupper(res));
	}

	template<class DATA_TYPE> static DATA_TYPE sum(DATA_TYPE val)
	{
		return val;
	}
	template<class DATA_TYPE> static DATA_TYPE minval(DATA_TYPE val)
	{
		return val;
	}
	template<class DATA_TYPE> static DATA_TYPE maxval(DATA_TYPE val)
	{
		return val;
	}
	template<class DATA_TYPE, class ...ARGS> static DATA_TYPE sum(DATA_TYPE val, ARGS ...args)
	{
		return val + sum(args...);
	}
	template<class DATA_TYPE, class ...ARGS> static DATA_TYPE avg(DATA_TYPE val, ARGS ...args)
	{
		return sum(val, args...) / (sizeof...(args) + 1);
	}
	template<class DATA_TYPE, class ...ARGS> static DATA_TYPE minval(DATA_TYPE val, ARGS ...args)
	{
		return val < minval(args...) ? val : minval(args...);
	}
	template<class DATA_TYPE, class ...ARGS> static DATA_TYPE maxval(DATA_TYPE val, ARGS ...args)
	{
		return val > maxval(args...) ? val : maxval(args...);
	}

	static string str(bool val)
	{
		return val ? "true" : "false";
	}
	static string str(char* str)
	{
		return str ? str : "";
	}
	static string str(void* ptr)
	{
		return to_string((long long)(ptr));
	}
	static string str(const char* str)
	{
		return str ? str : "";
	}
	static string str(const void* ptr)
	{
		return to_string((long long)(ptr));
	}
	static string str(const string& str)
	{
		return str;
	}
	static bool endwith(const string& str, const string& tag)
	{
		return str.length() >= tag.length() && memcmp(str.c_str() + str.length() - tag.length(), tag.c_str(), tag.length()) == 0;
	}
	static bool startwith(const string& str, const string& tag)
	{
		return str.length() >= tag.length() && memcmp(str.c_str(), tag.c_str(), tag.length()) == 0;
	}
	template<class DATA_TYPE> static string str(const DATA_TYPE& val)
	{
		return to_string(val);
	}
	template<class DATA_TYPE, char BEGIN = '"', char END = 0> static string quote(const DATA_TYPE& val)
	{
		return END ? BEGIN + str(val) + END : BEGIN + str(val) + BEGIN;
	}

	static int random(int begin = 0, int end = -1)
	{
		int mod = end - begin;
		int val = abs((int)(rand()));

		if (mod <= 0) return begin + val;

		return begin + val % mod;
	}

	int atoi(const char* str);
	double atof(const char* str);
	long long atol(const char* str);
	string format(const char* fmt, ...);
	int append(string& str, const string& msg);
	int format(string& str, const char* fmt, ...);
	int append(string& str, const char* fmt, ...);
	int vformat(string& str, const char* fmt, va_list args);

	bool async(sp<WorkItem> item);
	bool async(function<void()> func);
	bool timer(int delay, sp<WorkItem> item);
	bool timer(int delay, function<void()> func);
	bool delay(int delay, sp<WorkItem> item, int maxtimes = 1);
	bool delay(int delay, function<void()> func, int maxtimes = 1);

	string syscode(const string& str);
	string gbkcode(const string& str);
	string utfcode(const string& str);
	string translate(const string& str);
	string fill(const string& str, int len, bool left, char ch);
	string trim(const string& str, const string& space = " \r\n\t");
	string replace(const string& str, const string& src, const string& dest);

	vector<string> split(const string& str, const string& space);
	int split(vector<string>& vec, const string& str, const string& space);

	const string& EmptyString();
	string DecodeURL(const string& msg);
	string EncodeURL(const string& msg);
	SmartBuffer DecodeHex(const char* src, int len);
	SmartBuffer EncodeHex(const void* src, int len, bool upper = true);

	const char* GetProcessExePath();
	string GetParentPath(const string& path);
	string GetExtNameFromPath(const string& path);
	string GetFileNameFromPath(const string& path);
	int GetFileContent(string& content, const string& path);
	int GetFileContent(SmartBuffer& content, const string& path);
	int FindFile(vector<string>& vec, const string& path, const string& filter);
	int GetFolderContent(vector<string>& vec, const string& path, int flag = eNONE, bool containdots = false);
	int GetFolderContent(function<void(string, int, long, time_t)> func, const string& path, int flag = eNONE, bool containdots = false);
};

class ParamVector : public Object
{
protected:
	vector<string> datas;
	vector<E_PARAM_TYPE> types;

public:
	ParamVector()
	{
	}
	template<class DATA_TYPE> ParamVector(const DATA_TYPE& val)
	{
		add(val);
	}
	template<class DATA_TYPE, class ...ARGS> ParamVector(const DATA_TYPE& val, ARGS ...args)
	{
		add(val);
		add(args...);
	}

	void clear()
	{
		datas.clear();
		types.clear();
	}
	int size() const
	{
		return datas.size();
	}
	int asInt(int idx) const
	{
		return (int)asLong(idx);
	}
	long asLong(int idx) const
	{
		return *(long*)(datas[idx].c_str());
	}
	bool asBool(int idx) const
	{
		return stdx::atoi(asString(idx).c_str());
	}
	float asFloat(int idx) const
	{
		return (float)asDouble(idx);
	}
	double asDouble(int idx) const
	{
		return *(double*)(datas[idx].c_str());
	}
	string asString(int idx) const
	{
		switch(types[idx])
		{
			case eINT: return stdx::str(asLong(idx));
			case eDOUBLE: return stdx::str(asDouble(idx));
		}

		return datas[idx];
	}
	E_PARAM_TYPE type(int idx) const
	{
		return types[idx];
	}
	const string& data(int idx) const
	{
		return datas[idx];
	}
	string join(const string& spliter = ",")
	{
		return join(spliter, NULL);
	}
	string join(const string& spliter, function<string(string)> filter)
	{
		string res;
		size_t len = datas.size();

		if (len == 0) return res;

		if (filter)
		{
			for (size_t i = 0; i < len; i++)
			{
				res += spliter + filter(asString(i));
			}
		}
		else
		{
			for (size_t i = 0; i < len; i++)
			{
				res += spliter + asString(i);
			}
		}

		return res.substr(spliter.length());
	}
	string placeholders(const string& tag = "?", const string& spliter = ",") const
	{
		string res;
		size_t len = datas.size();

		if (len == 0) return res;

		while (len-- > 0) res += spliter + tag;

		return res.substr(spliter.length());
	}

	void add()
	{
		types.push_back(eNULL);
		datas.push_back(stdx::EmptyString());
	}
	void add(int val)
	{
		add((long)(val));
	}
	void add(long val)
	{
		types.push_back(eINT);
		datas.push_back(string((char*)(&val), (char*)(&val) + sizeof(long)));
	}
	void add(bool val)
	{
		types.push_back(eBOOL);
		datas.push_back(val ? "1" : "0");
	}
	void add(size_t val)
	{
		long tmp = val;
		types.push_back(eINT);
		datas.push_back(string((char*)(&tmp), (char*)(&tmp) + sizeof(long)));
	}
	void add(double val)
	{
		types.push_back(eDOUBLE);
		datas.push_back(string((char*)(&val), (char*)(&val) + sizeof(double)));
	}
	void add(char* val)
	{
		add((const char*)(val));
	}
	void add(const char* val)
	{
		types.push_back(val ? eSTRING : eNULL);
		datas.push_back(val ? val : "");
	}
	void add(const string& val)
	{
		types.push_back(eSTRING);
		datas.push_back(val);
	}
	void add(SmartBuffer buffer)
	{
		add((const void*)(buffer.str()), buffer.size());
	}
	void add(const void* data, int len)
	{
		types.push_back(data ? eBUFFER : eNULL);
		datas.push_back(data ? string((char*)(data), (char*)(data) + len) : stdx::EmptyString());
	}
	template<class DATA_TYPE> void add(const set<DATA_TYPE>& list)
	{
		for (const DATA_TYPE& val : list) add(val);
	}
	template<class DATA_TYPE> void add(const list<DATA_TYPE>& list)
	{
		for (const DATA_TYPE& val : list) add(val);
	}
	template<class DATA_TYPE> void add(const vector<DATA_TYPE>& list)
	{
		for (const DATA_TYPE& val : list) add(val);
	}
	template<class DATA_TYPE, class ...ARGS> void add(const DATA_TYPE& val, ARGS ...args)
	{
		add(val);
		add(args...);
	}
};

class StringCreator : public Object
{
private:
	string content;
	string linespliter;

public:
	StringCreator() : linespliter("\r\n")
	{
	}
	StringCreator(const char* str) : content(str), linespliter("\r\n")
	{
	}
	StringCreator(const string& str) : content(str), linespliter("\r\n")
	{
	}

public:
	void clear()
	{
		content.clear();
	}
	bool empty() const
	{
		return content.empty();
	}
	size_t size() const
	{
		return content.length();
	}
	size_t length() const
	{
		return content.length();
	}
	const char* str() const
	{
		return content.c_str();
	}
	string toString() const
	{
		return content;
	}
	const string& getContent() const
	{
		return content;
	}
	void setContent(const string& msg)
	{
		content = msg;
	}
	const string& getLineSpliter() const
	{
		return linespliter;
	}
	void setLineSpliter(const string& spliter)
	{
		linespliter = spliter;
	}

	StringCreator& tr()
	{
		content += linespliter;
		return *this;
	}
	StringCreator& puts(const char* str)
	{
		content += str;
		return tr();
	}
	StringCreator& puts(const string& str)
	{
		content += str;
		return tr();
	}
	StringCreator& printf(const char* fmt, ...)
	{
		va_list args;

		va_start(args, fmt);
		stdx::vformat(content, fmt, args);
		va_end(args);

		return *this;
	}

	StringCreator& operator << (char ch)
	{
		content.push_back(ch);
		return *this;
	}
	StringCreator& operator << (char* str)
	{
		content += str;
		return *this;
	}
	StringCreator& operator << (string& str)
	{
		content += str;
		return *this;
	}
	StringCreator& operator << (const char* str)
	{
		content += str;
		return *this;
	}
	StringCreator& operator << (const string& str)
	{
		content += str;
		return *this;
	}
	StringCreator& operator << (const Object& obj)
	{
		content += obj.toString();
		return *this;
	}
	template<class NUMBER_TYPE> StringCreator& operator << (NUMBER_TYPE val)
	{
		content += stdx::str(val);
		return *this;
	}
};

static string& operator += (string& str, const Object& obj)
{
	return str += obj.toString();
}

static std::ostream& operator << (std::ostream& out, const Object& obj)
{
	return out << obj.toString();
}

static StringCreator& operator << (StringCreator& out, const Object& obj)
{
	return out << obj.toString();
}

static string operator + (const string& str, const Object& obj)
{
	return str + obj.toString();
}

template<typename T> class TSQueue : public Object
{
protected:
	size_t maxsz;
	queue<T> dataqueue;
	mutable SpinMutex mtx;

public:
	bool pop(T& val)
	{
		SpinLocker lk(mtx);
		CHECK_FALSE_RETURN(dataqueue.size() > 0);
		val = dataqueue.front();
		dataqueue.pop();
		return true;
	}
	bool empty() const
	{
		SpinLocker lk(mtx);
		return dataqueue.empty();
	}
	size_t size() const
	{
		SpinLocker lk(mtx);
		return dataqueue.size();
	}
	bool push(const T& val)
	{
		SpinLocker lk(mtx);
		if (maxsz > 0 && dataqueue.size() >= maxsz) return false;
		dataqueue.push(val);
		return true;
	}
	TSQueue(size_t maxsz = 0)
	{
		this->maxsz = maxsz;
	}
};

template<typename KEY, typename VAL> class TSMap : public Object
{
protected:
	map<KEY, VAL> datamap;
	mutable SpinMutex mtx;

public:
	void clear()
	{
		SpinLocker lk(mtx);
		datamap.clear();
	}
	bool empty() const
	{
		SpinLocker lk(mtx);
		return datamap.empty();
	}
	size_t size() const
	{
		SpinLocker lk(mtx);
		return datamap.size();
	}
	bool remove(const KEY& key)
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end()) return false;
		datamap.erase(it);
		return true;
	}
	void clear(function<bool(VAL&)> func)
	{
		SpinLocker lk(mtx);
		auto it = datamap.begin();
		while (it != datamap.end())
		{
			if (func(it->second))
			{
				datamap.erase(it++);
			}
			else
			{
				++it;
			}
		}
	}
	int get(map<KEY, VAL>& resmap) const
	{
		SpinLocker lk(mtx);
		for (const auto& item : datamap) resmap[item.first] = item.second;
		return resmap.size();
	}
	bool get(const KEY& key, VAL& val) const
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end()) return false;
		val = it->second;
		return true;
	}
	void set(const map<KEY, VAL>& attrmap)
	{
		SpinLocker lk(mtx);
		for (const auto& item : attrmap) datamap[item.first] = item.second;
	}
	void set(const KEY& key, const VAL& val)
	{
		SpinLocker lk(mtx);
		datamap[key] = val;
	}
	bool update(const KEY& key, function<void(VAL&)> func)
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end()) return false;
		func(it->second);
		return true;
	}
	size_t get(const vector<KEY> keylist, map<KEY, VAL>& resmap)
	{
		SpinLocker lk(mtx);
		for (const KEY& key : keylist)
		{
			auto it = datamap.find(key);
			if (it == datamap.end()) continue;
			resmap[key] = it->second;
		}
		return resmap.size();
	}
};

template <typename KEY, typename VAL> class CacheMap
{
protected:
	class Head
	{
	public:
		KEY key;
		long weight = 0;

		bool operator < (const Head& obj) const
		{
			return weight < obj.weight;
		}
	};

	class Node
	{
	public:
		VAL data;
		Head head;

		Node()
		{
		}
		Node(const KEY& key, const VAL& val, int weight) : data(val)
		{
			head.key = key;
			head.weight = weight;
		}
	};

protected:
	size_t maxsz;
	mutable SpinMutex mtx;
	map<KEY, Node> datamap;
	function<void(long&)> func;

	int check()
	{
		long avg = 0;
		auto it = datamap.begin();
		priority_queue<Head> queue;
		const int maxlen = stdx::minval(datamap.size() / 8, 10000);

		for (int i = 0; i < maxlen; i++)
		{
			avg += it->second.head.weight;
			queue.push(it->second.head);
			++it;
		}

		while (it != datamap.end())
		{
			Head& data = it->second.head;

			if (data.weight < queue.top().weight)
			{
				queue.pop();
				queue.push(data);
			}

			avg += data.weight;
			++it;
		}

		avg /= datamap.size();

		for (int i = 0; i < maxlen; i++)
		{
			datamap.erase(queue.top().key);

			queue.pop();
		}

		return avg;
	}

public:
	void clear()
	{
		SpinLocker lk(mtx);
		datamap.clear();
	}
	bool empty() const
	{
		SpinLocker lk(mtx);
		return datamap.empty();
	}
	size_t size() const
	{
		SpinLocker lk(mtx);
		return datamap.size();
	}
	bool remove(const KEY& key)
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end()) return false;
		datamap.erase(it);
		return true;
	}
	CacheMap(size_t maxsz = 10000)
	{
		this->func = [](long& val){
			++val;
		};
		this->init(maxsz);
	}
	void init(size_t maxsz = 10000)
	{
		this->maxsz = stdx::maxval(maxsz, 100);
	}
	void clear(function<bool(VAL&)> func)
	{
		vector<KEY> vec;
		SpinLocker lk(mtx);
		for (auto& item : datamap)
		{
			if (func(item.second.data)) vec.push_back(item.first);
		}
		for (auto& item : vec) datamap.erase(item);
	}
	bool get(const KEY& key, VAL& val)
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end()) return false;
		val = it->second.data;
		func(it->second.head.weight);
		return true;
	}
	void weight(function<void(long&)> func)
	{
		this->func = func;
	}
	void set(const KEY& key, const VAL& val)
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end())
		{
			int weight = datamap.size() >= maxsz ? check() : 0;
			datamap[key] = Node(key, val, weight);
		}
		else
		{
			it->second.data = val;
		}
	}
	bool update(const KEY& key, function<void(VAL&)> func)
	{
		SpinLocker lk(mtx);
		auto it = datamap.find(key);
		if (it == datamap.end()) return false;
		func(it->second.data);
		return true;
	}
	size_t get(const vector<KEY> keylist, map<KEY, VAL>& resmap)
	{
		SpinLocker lk(mtx);
		for (const KEY& key : keylist)
		{
			auto it = datamap.find(key);
			if (it == datamap.end()) continue;
			resmap[key] = it->second.data;
			func(it->second.head.weight);
		}
		return resmap.size();
	}
};

class TaskQueue : public Object
{
	class Queue
	{
	protected:
		size_t str = 0;
		size_t end = 0;
		size_t maxsz = 0;
		sp<WorkItem>* arr = NULL;

	public:
		~Queue()
		{
			init(0);
		}
		bool empty() const
		{
			return str == end;
		}
		size_t size() const
		{
			return end < str ? maxsz + end - str + 1 : end - str;
		}
		size_t capacity() const
		{
			return maxsz;
		}
		void init(size_t maxsz)
		{
			if (arr) delete[] arr;
			if (maxsz > 0) arr = new sp<WorkItem>[maxsz + 1];
			this->maxsz = maxsz;
			this->str = 0;
			this->end = 0;
		}
		size_t pop(sp<WorkItem>& val)
		{
			size_t len = size();
			if (len == 0) return 0;
			std::swap(val, arr[str++]);
			if (str > maxsz) str = 0;
			return len;
		}
		size_t push(sp<WorkItem>& val)
		{
			size_t len = size();
			if (len++ == maxsz) return 0;
			std::swap(val, arr[end++]);
			if (end > maxsz) end = 0;
			return len;
		}
	};

private:
	Queue queue;
	size_t threads = 0;
	mutable SpinMutex mtx;
	mutable SpinMutex desmtx;
	atomic_int curdepth = {0};
	atomic_int threadcount = {0};
	map<long, function<void()>> destroymap;

	size_t pop(sp<WorkItem>& item)
	{
		SpinLocker lk(mtx);
		return queue.pop(item);
	}

public:
	void run();
	bool push(sp<WorkItem> item);
	bool start(size_t threads = 4, size_t maxsz = 10000);

	void cancelDestroyFunc();
	bool removeDestroyFunc();
	bool trySetDestroyFunc(function<void()> func);

	void stop()
	{
		threads = 0;
	}
	void wait()
	{
		while (curdepth > 0) Sleep(1);
	}
	bool empty() const
	{
		SpinLocker lk(mtx);
		return queue.empty();
	}
	size_t size() const
	{
		SpinLocker lk(mtx);
		return queue.size();
	}
	size_t getThreads() const
	{
		return threads;
	}

	static TaskQueue* Instance();
};

class TimerTaskQueue : public Object
{
	struct Task
	{
		int delay = -1;
		int times = -1;
		int maxtimes = -1;
		long long rtime = -1;
		sp<WorkItem> task = NULL;

		bool update(long long now);

		bool operator < (const Task& task) const
		{
			return rtime > task.rtime;
		}
		bool init(int delay, int maxtimes, const sp<WorkItem>& task, long long now = 0)
		{
			if (now <= 0) CHECK_FALSE_RETURN((now = GetTime() / 1000) > 0);

			if (task) this->task = task;
			this->maxtimes = maxtimes;
			this->delay = delay;
			this->times = -1;

			return update(now);
		}
	};

	SpinMutex mtx;
	int started = 0;
	priority_queue<Task> queue;

	bool get(Task& task);

public:
	void run();
	void check(function<bool(sp<WorkItem>)> filter);
	bool push(sp<WorkItem> task, int delay, int maxtimes = 0);
	bool daily(sp<WorkItem> task, const string& time, int maxtimes = 0);
	bool update(int delay, int maxtimes, function<bool(sp<WorkItem>)> filter);

	static TimerTaskQueue* Instance();
};

#ifndef XG_PROCESS_GLOBALPTR_ENVNAME_HDR
#define XG_PROCESS_GLOBALPTR_ENVNAME_HDR	"XG_GPTR_ENV_"
#endif

#define START_APP(APPCLASS)						\
int main(int argc, char* argv[])				\
{												\
	Process::Instance(argc, argv);				\
	sp<APPCLASS> app = newsp<APPCLASS>();		\
	Process::GetApplication(app.get());			\
	return app->main() ? 0 : XG_ERROR;			\
}

#define XG_DEFINE_GLOBAL_VARIABLE(TYPE)								\
static TYPE* ptr = NULL; if (ptr) return ptr;						\
{Locker lk(Process::Instance()->getMutex());						\
string name = stdx::format("GPTR_%s_%s_%s",							\
stdx::GetFileNameFromPath(__FILE__).c_str(), #TYPE, __FUNCTION__);	\
if (ptr = (TYPE*)(Process::GetObject(name))) return ptr;			\
Process::SetObject(name, ptr = new TYPE());							\
return ptr;}

#define CATCH_EXCEPTION(CODE)													\
try																				\
{CODE}																			\
catch(const Exception& e)														\
{																				\
	fprintf(stderr, "catch exception[%d][%s]\n", e.getErrorCode(), e.what());	\
}																				\
catch(const exception& e)														\
{																				\
	fprintf(stderr, "catch exception[%s]\n", e.what());							\
}																				\
catch(...)																		\
{																				\
	fprintf(stderr, "catch unknown exception\n");								\
}

class Application;

typedef int PROCESS_T;

struct ProcessData
{
	string name;
	string path;
	PROCESS_T id;
	PROCESS_T pid;
};

class Process : public Object
{
protected:
	Mutex mutex;
	char** argv;
	string appname;
	time_t startime;
	vector<string> vec;
	mutable SpinMutex mtx;
	map<string, string> paramap;
	map<string, const void*> objmap;

	Process(const Process&);
	int init(int argc, char** argv);
	Process operator = (const Process&);
	
#ifndef XG_LINUX
	static HANDLE GetProcessHandle(PROCESS_T id);
	static bool EnableDebugPrivilege(HANDLE handle);
#endif

public:
	Process();
	Mutex& getMutex();
	int getParamCount() const;
	int getObjectCount() const;
	char** getCmdParam() const;
	int getCmdParamCount() const;
	const char* getAppname() const;
	const char* getCmdParam(int index) const;
	string getParam(const string& key) const;
	const void* getObject(const string& key) const;
	const char* getCmdParam(const string& key) const;
	void setObject(const string& key, const void* obj);
	void setParam(const string& key, const string& val);

public:
	static Process* Instance();
	static Process* Instance(int argc, char** argv);
	static Application* GetApplication(Application* obj = NULL);

	static bool InitDaemon();
	static void CheckSingle();
	static bool IsStartedByExplorer();
	static bool SetCommonExitSignal();
	static bool Wait(PROCESS_T handle);
	static string GetCurrentDirectory();
	static PROCESS_T GetCurrentProcess();
	static void CommonExitFunc(int signum);
	static string GetEnv(const string& key);
	static bool GetProcessExePath(string& path);
	static bool SetDaemonCommand(const string& cmd);
	static bool Kill(PROCESS_T handle, int flag = 0);
	static PROCESS_T GetParentProcess(PROCESS_T handle);
	static bool SetCurrentDirectory(const string& path);
	static bool SetEnv(const string& key, const string& val);
	static bool RegisterLibraryPath(const string& path = "");
	static bool RegisterExecutablePath(const string& path = "");
	static bool GetProcessExePath(PROCESS_T handle, string& path);
	static bool RegisterVariable(const string& key, const string& val);

	static int GetSystemProcessList(vector<ProcessData>& vec);
	static int GetSystemProcessListByName(vector<ProcessData>& vec, const string& name);
	static int GetSystemProcessListByExeName(vector<ProcessData>& vec, const string& path);

	static bool SetGlobalVariable(const string& name, const void* ptr)
	{
		string key = XG_PROCESS_GLOBALPTR_ENVNAME_HDR;
		
		return SetEnv(key += name + stdx::str(GetCurrentProcess()), stdx::str(ptr));
	}

	template <class DATA_TYPE>
	static bool GetGlobalVariable(const string& name, DATA_TYPE* &ptr)
	{
		string key = XG_PROCESS_GLOBALPTR_ENVNAME_HDR;
		string val = GetEnv(key += name + stdx::str(GetCurrentProcess()));

		if (val.empty()) return false;

		ptr = (DATA_TYPE*)(stdx::atol(val.c_str()));

		return true;
	}

	template <class DATA_TYPE>
	static bool GetGlobalVariable(const string& name, DATA_TYPE* &ptr, bool created)
	{
		string key = XG_PROCESS_GLOBALPTR_ENVNAME_HDR;
		string val = GetEnv(key += name + stdx::str(GetCurrentProcess()));

		if (val.empty())
		{
			if (created)
			{
				if (SetGlobalVariable(name, ptr = new DATA_TYPE())) return true;
				
				delete ptr;
				ptr = NULL;
			}
			
			return false;
		}

		ptr = (DATA_TYPE*)(stdx::atol(val.c_str()));

		return true;
	}

	static int GetParamCount()
	{
		return Instance()->getParamCount();
	}
	static char** GetCmdParam()
	{
		return Instance()->getCmdParam();
	}
	static time_t GetStartTime()
	{
		return Instance()->startime;
	}
	static int GetCmdParamCount()
	{
		return Instance()->getCmdParamCount();
	}
	static const char* GetAppname()
	{
		return Instance()->getAppname();
	}
	static const char* GetCmdParam(int index)
	{
		return Instance()->getCmdParam(index);
	}
	static string GetParam(const string& key)
	{
		return Instance()->getParam(key);
	}
	static const char* GetCmdParam(const string& key)
	{
		return Instance()->getCmdParam(key);
	}
	static void SetParam(const string& key, const string& val)
	{
		Instance()->setParam(key, val);
	}

	static int GetObjectCount()
	{
		return Instance()->getObjectCount();
	}
	static const void* GetObject(const string& key)
	{
		return Instance()->getObject(key);
	}
	static void SetObject(const string& key, const void* obj)
	{
		Instance()->setObject(key, obj);
	}
};

class Application : public Object
{
public:
	virtual bool main();
	virtual void clean();
	static void puts(const string& msg);
	static void printf(const char* fmt, ...);

public:
	static int GetParamCount()
	{
		return Process::GetParamCount();
	}
	static char** GetCmdParam()
	{
		return Process::GetCmdParam();
	}
	static int GetCmdParamCount()
	{
		return Process::GetCmdParamCount();
	}
	static const char* GetAppname()
	{
		return Process::GetAppname();
	}
	static const char* GetCmdParam(int index)
	{
		return Process::GetCmdParam(index);
	}
	static string GetParam(const string& key)
	{
		return Process::GetParam(key);
	}
	static void SetTitle(const string& title)
	{
#ifndef XG_LINUX
		SetConsoleTitleA(stdx::syscode(title).c_str());
#endif
	}
	static const char* GetCmdParam(const string& key)
	{
		return Process::GetCmdParam(key);
	}
	static void SetParam(const string& key, const string& val)
	{
		Process::SetParam(key, val);
	}
	
	static int GetObjectCount()
	{
		return Process::GetObjectCount();
	}
	static const void* GetObject(const string& key)
	{
		return Process::GetObject(key);
	}
	static void SetObject(const string& key, const void* obj)
	{
		Process::SetObject(key, obj);
	}
};

class DllFile : public Object
{
public:
	typedef map<string, sp<DllFile>> ObjectMap;

protected:
	string path;
	time_t ctime;
	DLLFILE_T handle;

	static SpinMutex* GetMutex();
	static ObjectMap* GetObjectMap();

public:
	DllFile();
	~DllFile();
	void close();
	bool open(const string& path);
	void* getAddress(const string& name) const;

	static string GetLastPath();
	static string GetErrorString();
	static bool Remove(sp<DllFile> dll);
	static bool Remove(const string& path);
	static sp<DllFile> Get(const string& path, bool created = true, bool saved = true);

	time_t getLoadTime() const
	{
		return ctime;
	}
	const string& getPath() const
	{
		return path;
	}
	template <typename FUNC_PTR> bool read(FUNC_PTR& func, const char* name) const
	{
		return (func = (FUNC_PTR)(getAddress(name))) ? true : false;
	}
};

class LineCommand : public Object
{
protected:
	vector<string> vec;

public:
	int init(const string& cmd, int* endpos = NULL);

public:
	bool empty() const
	{
		return vec.empty();
	}
	size_t size() const
	{
		return vec.size();
	}
	const char* get(int idx) const
	{
		return (idx >= 0 && idx < size()) ? vec[idx].c_str() : NULL;
	}
	const char* operator [] (int idx) const
	{
		return get(idx);
	}
};

class ContentNode : public Object
{
protected:
	string valspliter;
	string keyspliter;
	string endspliter;
	vector<string> vec;
	map<string, string> content;

public:
	void clear();
	ContentNode();
	string toString() const;
	string& operator [] (const string& key);
	bool setOrder(const string& key, int idx);
	const string& getValue(const string& key) const;
	bool parse(const string& msg, bool inited = true);
	bool setValue(const string& key, const string& val, bool append);

	bool empty() const
	{
		return content.empty();
	}
	size_t size() const
	{
		return content.size();
	}
	const string& getKeySpliter() const
	{
		return keyspliter;
	}
	const string& getEndSpliter() const
	{
		return endspliter;
	}
	const string& getValueSpliter() const
	{
		return valspliter;
	}
	const vector<string>& getKeys() const
	{
		return vec;
	}
	void setKeySpliter(const string& spliter)
	{
		keyspliter = spliter;
	}
	void setEndSpliter(const string& spliter)
	{
		endspliter = spliter;
	}
	void setValueSpliter(const string& spliter)
	{
		valspliter = spliter;
	}
	const map<string, string>& getDataMap() const
	{
		return content;
	}
	void sort(std::function<bool(const string&, const string&)> func)
	{
		std::sort(vec.begin(), vec.end(), func);
	}
	template<class DATA_TYPE> bool setValue(const string& key, const DATA_TYPE& val)
	{
		return setValue(key, stdx::str(val), false);
	}
};
///////////////////////////////////////////////////////////////////
#endif